#ifndef __baker_Ray_h__
#define __baker_Ray_h__

#include "Prerequire.h"
#include "Vector.h"

namespace baker
{
    /** A Ray repersented by a point and a direction.
    */
    template< typename VEC_TYPE >
    struct Ray
    {
        /** The origin of the Ray.
        */
        VEC_TYPE orig;

        /** The direction of the Ray.
        */
        VEC_TYPE dir;

        /** Construct a Ray with the ray-origin and the direction
        */
        Ray( const VEC_TYPE & orig
           , const VEC_TYPE & dir
           )
           : orig( orig )
           , dir( dir )
        {
        }

        /** Get a point among the Ray such that result = Ray.Orig + Ray.Dir * t
        */
        inline VEC_TYPE getPoint( real t ) const
        {
            return orig + ( dir * t );
        }

        /** Project of the input point, p, perpendicularly to the Ray;
            and return the parameter of the projection.
            @return A parameter t such that r = Ray.Orig + Ray.Dir * t; And ( p - r ) is perpendicular to Ray.Dir
        */
        inline real project( const VEC_TYPE & p ) const
        {
            return dot( ( p - orig ), dir ) / lengthSq( dir );
        }

        /** Get the closest (perpendicular) distance from a point to the Ray.
        */
        real dist( const VEC_TYPE & p ) const
        {
            VEC_TYPE p2 = getPoint( project( p ) );

            return length( p2 - p );
        }
    };

    /** Ray2 */
    typedef Ray<Vec2> Ray2;

    /** Ray3 */
    typedef Ray<Vec3> Ray3;
}

#endif  // __baker_Ray_h__
